
// Copyright (C) 2010-2011 Luca Piccioni
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//  
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//  
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

namespace Derm.Render
{
	/// <summary>
	/// Plane abstraction.
	/// </summary>
	public class Plane
	{
		#region Constructors

		/// <summary>
		/// Construct a plane from a normal and a distance from origin.
		/// </summary>
		/// <param name="normal">
		/// A <see cref="Vertex3f"/> representing the plane normal.
		/// </param>
		/// <param name="d">
		/// A <see cref="System.Single"/> representing the distance between the
		/// plane and the origin.
		/// </param>
		public Plane(Vertex3f normal, float d)
		{
			Normal = normal;
			Distance = -d;
		}

		/// <summary>
		/// Construct a plane from a normal and a point.
		/// </summary>
		/// <param name="normal">
		/// A <see cref="Vertex3f"/> representing the plane normal.
		/// </param>
		/// <param name="point">
		/// A <see cref="Vertex3f"/> representing the point considered for
		/// constructing the plane.
		/// </param>
		public Plane(Vertex3f normal, Vertex3f point)
		{
			Normal = normal;
			Distance = -(normal * point);
		}

		/// <summary>
		/// Construct a plane from 3 coplanar points.
		/// </summary>
		/// <param name="v1">
		/// A <see cref="Vertex3f"/> representing one plane coplanar point.
		/// </param>
		/// <param name="v2">
		/// A <see cref="Vertex3f"/> representing one plane coplanar point.
		/// </param>
		/// <param name="v3">
		/// A <see cref="Vertex3f"/> representing one plane coplanar point.
		/// </param>
		public Plane(Vertex3f v1, Vertex3f v2, Vertex3f v3)
		{
			Vertex3f edge1 = v2 - v1, edge2 = v3 - v1;

			Normal = edge1 ^ edge2;
			Distance = -(Normal * v1);
		}

		#endregion

		#region Plane Definition

		/// <summary>
		/// Plane normal vector.
		/// </summary>
		public Vertex3f Normal
		{
			get { return (mNormal); }
			set {
				mNormal = value;
				mNormal.Normalize();
			}
		}

		/// <summary>
		/// 
		/// </summary>
		public float Distance
		{
			get { return (mDistance); }
			set { mDistance = value; }
		}

		/// <summary>
		/// Plane normal.
		/// </summary>
		private Vertex3f mNormal;
		/// <summary>
		/// Distance from origin.
		/// </summary>
		private float mDistance;

		#endregion

		#region Plane Operations

		/// <summary>
		/// Compute distance between a point and this plane.
		/// </summary>
		/// <param name="p">
		/// A <see cref="Vertex3f"/> representing a point.
		/// </param>
		/// <returns>
		/// It returns the distance between a point and this plane. In the case
		/// the distance is positive, the point is on the positive side of the
		/// plane (following Normal direction), otherwise the distance is
		/// negative.
		/// </returns>
		public float GetDistance(Vertex3f p)
		{
			return ((Normal * p) + Distance);
		}

		#endregion
	}
}